package com.cryptape.cita_wallet.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.support.annotation.RawRes;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.MapUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.cryptape.cita_wallet.CytonApplication;
import com.cryptape.cita_wallet.activity.transfer.TransferActivity;
import com.cryptape.cita_wallet.bean.AllDetectionParameter;
import com.cryptape.cita_wallet.bean.MiningWithdrawDetailBean;
import com.cryptape.cita_wallet.bean.MyMIDBean;
import com.cryptape.cita_wallet.bean.VersionUpdateBean;
import com.cryptape.cita_wallet.constant.ConstantUtil;
import com.cryptape.cita_wallet.fragment.AppFragment;
import com.cryptape.cita_wallet.fragment.MyAppFragment;
import com.cryptape.cita_wallet.fragment.SettingsFragment;
import com.cryptape.cita_wallet.fragment.wallet.WalletFragment;
import com.cryptape.cita_wallet.item.Token;
import com.cryptape.cita_wallet.net.callback.CommonCallback;
import com.cryptape.cita_wallet.net.request.HttpRequestMode;
import com.cryptape.cita_wallet.service.ContractService;
import com.cryptape.cita_wallet.service.LanguageKeeper;
import com.cryptape.cita_wallet.service.http.CITARpcService;
import com.cryptape.cita_wallet.service.http.EthRpcService;
import com.cryptape.cita_wallet.service.http.TokenService;
import com.cryptape.cita_wallet.service.intent.CITATransactionCheckService;
import com.cryptape.cita_wallet.service.intent.EtherTransactionCheckService;
import com.cryptape.cita_wallet.util.AppUtils;
import com.cryptape.cita_wallet.util.HProgressDialogUtils;
import com.cryptape.cita_wallet.util.RSAUtils;
import com.cryptape.cita_wallet.util.UpdateAppHttpUtil;
import com.cryptape.cita_wallet.util.db.DBWalletUtil;
import com.cryptape.cita_wallet.util.db.SharePrefUtil;
import com.cryptape.cita_wallet.util.permission.PermissionUtil;
import com.cryptape.cita_wallet.util.permission.RuntimeRationale;
import com.cryptape.cita_wallet.util.qrcode.CodeUtils;
import com.cryptape.cita_wallet.util.url.HttpCITAUrls;
import com.mangoworld.android.R;
import com.vector.update_app.UpdateAppBean;
import com.vector.update_app.UpdateAppManager;
import com.vector.update_app.service.DownloadService;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.Permission;
import com.yanzhenjie.permission.runtime.PermissionRequest;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

//import com.cryptape.cita_wallet.service.LanguageKeeper;
;

/**
 * Created by duanyytop on 2018/4/17
 */
public class MainActivity extends NBaseActivity {
    public static final String EXTRA_TAG = "extra_tag";
    public static final int REQUEST_CODE_SCAN = 0x01;
    private static final int APPCAHIN_TRANSACTION_FETCH_PERIOD = 300000;
    //    private static final int ETHER_TRANSACTION_FETCH_PERIOD = 300000;
    private static final int ETHER_TRANSACTION_FETCH_PERIOD = 300000;

    private RadioGroup navigation;
    //    private AppFragment appFragment;
    private WalletFragment walletFragment;
    private SettingsFragment settingsFragment;
    private MyAppFragment myAppFragment;
    private FragmentManager fMgr;

    @Override
    protected int getContentLayout() {
        return R.layout.activity_main;
    }

    @Override
    protected int getStatusBarColor() {
        return getResources().getColor(R.color.white);
    }

    @Override
    protected void initView() {
        navigation = findViewById(R.id.navigation);
        navigation.check(RadioGroup.NO_ID);
        List<String> address = DBWalletUtil.getAllWalletAddress(this);
        String registrationId = SharePrefUtil.getRegistrationID();
        try {
            AllDetectionParameter params = new AllDetectionParameter();
            params.setAddrs(address);
            params.setRegistrationId(registrationId);
            params.setType("1");
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.getAllDetection(MainActivity.this, content, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        PermissionRequest request = AndPermission.with(this).runtime().permission(Permission.Group.STORAGE);
        request.rationale(new RuntimeRationale()).onGranted(permissions -> {
        });
        request.onDenied(permissions -> {
            PermissionUtil.showSettingDialog(this, permissions);
        });
        request.start();
    }

    @Override
    protected void initData() {
        fMgr = getSupportFragmentManager();
        startCheckCITATransaction();
        startCheckEtherTransaction();
        initLanguageSetBroadCast();
        getVersion();
//        try {
//            checkMemberExistsAddress();
//        }catch (Exception e){
//
//        }
//        PushManager.getInstance().bindPush();
    }

    private void queryMid() {
        try {
            String address = DBWalletUtil.getCurrentWallet(CytonApplication.getInstance()).address;
            Map params = MapUtils.newHashMap();
            params.put("address", address);
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.findMid(MainActivity.this, content, true, new CommonCallback() {
                @Override
                public void onSuccess(Object data, String successMsg, int responseSuccessCode) {
                    MyMIDBean midBean = (MyMIDBean) data;
                    if (midBean != null) {
                        String mid = midBean.getLnvitationCode();
                        CytonApplication.getInstance().MIDCode = mid;
                    } else {
                        CytonApplication.getInstance().MIDCode = "";
                    }
                }

                @Override
                public void onFailure(String msg, int responseFailCode) {
                    CytonApplication.getInstance().MIDCode = "";
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void startCheckCITATransaction() {
        CITARpcService.init(mActivity, HttpCITAUrls.CITA_NODE_URL);
        Intent intent = new Intent();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                CITATransactionCheckService.enqueueWork(mActivity, intent);
            }
        }, 0, APPCAHIN_TRANSACTION_FETCH_PERIOD);
    }

    public static int getVersionCode(Context context) {
        return getPackageInfo(context).versionCode;
    }

    private static PackageInfo getPackageInfo(Context context) {
        PackageInfo pi = null;

        try {
            PackageManager pm = context.getPackageManager();
            pi = pm.getPackageInfo(context.getPackageName(),
                    PackageManager.GET_CONFIGURATIONS);

            return pi;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return pi;
    }

    private void getVersion() {
        try {
            Map params = MapUtils.newHashMap();
            params.put("appType", "1");
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.getVersion(MainActivity.this, content, true, new CommonCallback() {
                @Override
                public void onSuccess(Object data, String successMsg, int responseSuccessCode) {
                    VersionUpdateBean versionUpdate = (VersionUpdateBean) data;
                    int versionCode = getVersionCode(MainActivity.this);
                    if (Integer.parseInt(versionUpdate.getVersioncode()) <= versionCode) {
                        return;
                    }
                    String apkUrl = versionUpdate.getDownload();
                    UpdateAppBean updateAppBean = new UpdateAppBean();
                    updateAppBean.setApkFileUrl(apkUrl);//设置 apk 的下载地址
                    String path = "";
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {
                        try {
                            path = getExternalCacheDir().getAbsolutePath();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (TextUtils.isEmpty(path)) {
                            path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
                        }
                    } else {
                        path = getCacheDir().getAbsolutePath();
                    }
                    updateAppBean.setTargetPath(path); //设置apk 的保存路径
                    updateAppBean.setHttpManager(new UpdateAppHttpUtil()); //实现网络接口，只实现下载就可以
                    UpdateAppManager.download(MainActivity.this, updateAppBean, new DownloadService.DownloadCallback() {
                        @Override
                        public void onStart() {
                            HProgressDialogUtils.showHorizontalProgressDialog(MainActivity.this, "下载进度", false);
                            Log.d("下载", "onStart() called");
                        }

                        @Override
                        public void onProgress(float progress, long totalSize) {
                            HProgressDialogUtils.setProgress(Math.round(progress * 100));
                            Log.d("下载", "onProgress() called with: progress = [" + progress + "], totalSize = [" + totalSize + "]");
                        }

                        @Override
                        public void setMax(long totalSize) {
                            Log.d("下载", "setMax() called with: totalSize = [" + totalSize + "]");
                        }

                        @Override
                        public boolean onFinish(File file) {
                            HProgressDialogUtils.cancel();
                            Log.d("下载", "onFinish() called with: file = [" + file.getAbsolutePath() + "]");
                            return true;
                        }

                        @Override
                        public void onError(String msg) {
                            HProgressDialogUtils.cancel();
                            Log.e("下载", "onError() called with: msg = [" + msg + "]");
                        }

                        @Override
                        public boolean onInstallAppAndAppOnForeground(File file) {
                            Log.d("下载", "onInstallAppAndAppOnForeground() called with: file = [" + file + "]");
                            return false;
                        }
                    });
                }

                @Override
                public void onFailure(String msg, int responseFailCode) {
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void startCheckEtherTransaction() {
        EthRpcService.initNodeUrl();
        Intent intent = new Intent();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                EtherTransactionCheckService.enqueueWork(mActivity, intent);
            }
        }, 0, ETHER_TRANSACTION_FETCH_PERIOD);
    }

    @Override
    protected void initAction() {
        navigation.setOnCheckedChangeListener((group, checkedId) -> {
            FragmentTransaction transaction = fMgr.beginTransaction();
            hideFragments(transaction);
            switch (checkedId) {
                case R.id.navigation_application:
                    if (myAppFragment == null) {
                        myAppFragment = new MyAppFragment();
                        transaction.add(R.id.fragment, myAppFragment);
                    } else {
                        transaction.show(myAppFragment);
                    }
                    break;
                case R.id.navigation_wallet:
                    if (DBWalletUtil.getCurrentWallet(mActivity) == null) {
                        startActivity(new Intent(mActivity, AddWalletActivity.class));
                    } else {
                        if (walletFragment == null) {
                            walletFragment = new WalletFragment();
                            transaction.add(R.id.fragment, walletFragment);
                        } else {
                            transaction.show(walletFragment);
                        }
                    }
//                    checkMemberExistsAddress();

//                    try {
//                        checkMemberExistsAddress();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    } catch (ExecutionException e) {
//                        e.printStackTrace();
//                    }
//                    try {
//                        roundDetail();
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
                    break;
                case R.id.navigation_settings:
                    if (settingsFragment == null) {
                        settingsFragment = new SettingsFragment();
                        transaction.add(R.id.fragment, settingsFragment);
                    } else {
                        transaction.show(settingsFragment);
                    }
                    break;
                default:
//                    if (appFragment == null) {
//                        appFragment = new AppFragment();
//                        transaction.add(R.id.fragment, appFragment);
//                    } else {
//                        transaction.show(appFragment);
//                    }
                    if (DBWalletUtil.getCurrentWallet(mActivity) == null) {
                        startActivity(new Intent(mActivity, AddWalletActivity.class));
                    } else {
                        if (walletFragment == null) {
                            walletFragment = new WalletFragment();
                            transaction.add(R.id.fragment, walletFragment);
                        } else {
                            transaction.show(walletFragment);
                        }
                    }
                    break;
            }
            transaction.commitAllowingStateLoss();
        });

        String tag = getIntent().getStringExtra(EXTRA_TAG);
        setNavigationItem(tag == null ? WalletFragment.Companion.getTAG() : tag);

    }

    /**
     * Go to fragment with flag
     *
     * @param tag Fragment flag
     */
    public void setNavigationItem(String tag) {
        if (TextUtils.isEmpty(tag)) return;
        if (TextUtils.equals(tag, MyAppFragment.TAG)) {
            navigation.check(R.id.navigation_application);
        } else if (TextUtils.equals(tag, WalletFragment.Companion.getTAG())) {
            navigation.check(R.id.navigation_wallet);
        } else if (TextUtils.equals(tag, SettingsFragment.TAG)) {
            navigation.check(R.id.navigation_settings);
        }
    }

    /**
     * 隐藏所有的fragment
     */
    private void hideFragments(FragmentTransaction transaction) {
        if (myAppFragment != null) {
            transaction.hide(myAppFragment);
        }
        if (walletFragment != null) {
            transaction.hide(walletFragment);
        }
        if (settingsFragment != null) {
            transaction.hide(settingsFragment);
        }
    }


    private long exitTime = 0;

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
//            if (myAppFragment.isVisible())
//            {
//                if (myAppFragment.canGoBack()) {
//                    myAppFragment.goBack();
//                    return true;
//                } else
//
            {
                if ((System.currentTimeMillis() - exitTime) > 2000) {
                    Toast.makeText(this, R.string.press_back_finish, Toast.LENGTH_SHORT).show();
                    exitTime = System.currentTimeMillis();
                    return false;
                } else {
                    finish();
                    return true;
                }
            }
        } else {
            FragmentTransaction fragmentTransaction = fMgr.beginTransaction();
            hideFragments(fragmentTransaction);
            setNavigationItem(AppFragment.Companion.getTAG());
            return true;
        }

//        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) switch (requestCode) {
            case REQUEST_CODE_SCAN:
                if (null != data) {
                    Bundle bundle = data.getExtras();
                    if (bundle == null) return;
                    if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
                        String result = bundle.getString(CodeUtils.RESULT_STRING);
                        Intent intent;
                        switch (bundle.getInt(CodeUtils.STRING_TYPE)) {
                            case CodeUtils.STRING_UNVALID:
                                Toast.makeText(this, R.string.address_error, Toast.LENGTH_LONG).show();
                                break;
                            case CodeUtils.STRING_ADDRESS:
                                Token token = new Token(ConstantUtil.ETH_MAINNET, ConstantUtil.ETH, ConstantUtil.ETHEREUM_MAIN_ID);
                                intent = new Intent(mActivity, TransferActivity.class);
                                intent.putExtra(TransferActivity.EXTRA_TOKEN, token);
                                intent.putExtra(TransferActivity.EXTRA_ADDRESS, result);
                                startActivity(intent);
                                break;
                            case CodeUtils.STRING_KEYSTORE:
                                intent = new Intent(this, ImportWalletActivity.class);
                                intent.putExtra(ImportWalletActivity.INTENT_FROM, ImportWalletActivity.INTENT_FROM_VALUE);
                                intent.putExtra(ImportWalletActivity.QR_CODE_TYPE, ImportWalletActivity.QR_CODE_TYPE_KEYSTORE);
                                intent.putExtra(ImportWalletActivity.QR_CODE_VALUE, result);
                                startActivity(intent);
                                break;
                            case CodeUtils.STRING_WEB:
                                SimpleWebActivity.gotoSimpleWeb(this, result);
                                break;
                            case CodeUtils.STRING_PRIVATE_KEY:
                                intent = new Intent(this, ImportWalletActivity.class);
                                intent.putExtra(ImportWalletActivity.INTENT_FROM, ImportWalletActivity.INTENT_FROM_VALUE);
                                intent.putExtra(ImportWalletActivity.QR_CODE_TYPE, ImportWalletActivity.QR_CODE_TYPE_PRIVATEKEY);
                                intent.putExtra(ImportWalletActivity.QR_CODE_VALUE, result);
                                startActivity(intent);
                                break;
                        }
                    } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) {
                        Toast.makeText(this, R.string.qrcode_handle_fail, Toast.LENGTH_LONG).show();
                    }
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void finish() {
        super.finish();
//        System.exit(0);
        System.exit(0);
        Process.killProcess(Process.myPid());
    }

//    public void roundDetail() throws Exception{
//        String address = DBWalletUtil.getCurrentWallet(this).address;
//
//        List<Type> inputParam = new ArrayList<>();
//
//        // Output parameters
//        List<TypeReference<?>> outputParam = new ArrayList<>();
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint>() {
//        });
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint256>() {
//        });
//        outputParam.add(new TypeReference<Uint>() {
//        });
//        Function function = new Function("roundDetail", inputParam, outputParam);
//        EthCall call = request(function);
//        if(call.getError() == null){
//            List<Type> result = FunctionReturnDecoder.decode(call.getResult(), function.getOutputParameters());
//            Log.e("MainActivity",""+result.get(0).getValue().toString());
//        }
//    }


//    public void checkMemberExistsAddress() throws InterruptedException, ExecutionException {
//        // Input parameters
//        String address = DBWalletUtil.getCurrentWallet(this).address;
//
//        List<Type> inputParam = new ArrayList<>();
//        inputParam.add(new Address(address));
//
//        // Output parameters
//        List<TypeReference<?>> outputParam = new ArrayList<>();
//        outputParam.add(new TypeReference<Bool>(){});
//
//        EthCall call = request(new Function("checkMemberExistsAddress", inputParam, outputParam));
//
//    }

//    /**
//     * Constant function
//     */
//    private EthCall request(Function function) throws InterruptedException, ExecutionException {
//        String address = DBWalletUtil.getCurrentWallet(this).address;
//        Transaction transaction = Transaction.createEthCallTransaction(address,"0x5E737774e2E6b4fa371568b021cF4802d29c5604",
//                FunctionEncoder.encode(function));
////        Transaction transaction = Transaction.createEthCallTransaction(address,"0xCB00A25BDf7B58995554e852A9D820cE9C49C5B8",
////                FunctionEncoder.encode(function));
//        EthCall request = EthRpcService.service.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
//        Log.e("MainActivity",request.getValue()+" "+request.getJsonrpc()
//        );
//        return request;
//    }

    private String loadFile(Context context, @RawRes int rawRes) {
        byte[] buffer = new byte[0];
        try {
            InputStream in = context.getResources().openRawResource(rawRes);
            buffer = new byte[in.available()];
            int len = in.read(buffer);
            if (len < 1) {
                throw new IOException("Nothing is read.");
            }
        } catch (Exception ex) {
            Log.d("READ_JS_TAG", "Ex", ex);
        }
        return new String(buffer);
    }

    BroadcastReceiver mLanguageSetReceiver;

    private void initLanguageSetBroadCast() {
        mLanguageSetReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                AppUtils.restartApp();
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(LanguageKeeper.ACTION_CHANGE_LOACL_LANGUAGE);
        registerReceiver(mLanguageSetReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mLanguageSetReceiver);
    }

    @Override
    protected void onResume() {
        super.onResume();
        LogUtils.dTag("MainActivity==", "onResume===");
        queryMid();
//        updateContract();
    }

    public static void updateContract() {
        Observable.fromCallable(() -> {
            String result = ContractService.updateContract();
            return result;
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(String result) {
                LogUtils.dTag("MainActivity==", "result = " + result + " contract = " + ConstantUtil.getDEPOSITCONTRACT());
            }
        });
    }
}
